﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.Practices.ESB.Exception.Management;
using Microsoft.Practices.ESB.Resolver;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.XLANGs.BaseTypes;
using System.Xml;

namespace BizTalk.ESB.Extensions.Resolvers
{
    public class ServiceProxyRequestStaticResolver : IResolveProvider
    {
        Dictionary<string, string> IResolveProvider.Resolve(ResolverInfo resolverInfo, XLANGMessage message)
        {
            // Create instance of ServiceProxyResolution
            ServiceProxyRequestResolution svcpxyResolution = new ServiceProxyRequestResolution();

            // Call ResolveStatic
            return ResolveStatic(resolverInfo.Config, resolverInfo.Resolver, svcpxyResolution);
        }

        Dictionary<string, string> IResolveProvider.Resolve(string config, string resolver, System.Xml.XmlDocument message)
        {
            // Create instance of ServiceProxyResolution
            ServiceProxyRequestResolution svcpxyResolution = new ServiceProxyRequestResolution();

            // Call ResolveStatic
            return ResolveStatic(config, resolver, svcpxyResolution);
        }

        Dictionary<string, string> IResolveProvider.Resolve(string config, string resolver, IBaseMessage message, IPipelineContext pipelineContext)
        {
            // Create instance of ServiceProxyResolution
            ServiceProxyRequestResolution svcpxyResolution = new ServiceProxyRequestResolution();

            // Call ResolveStatic
            return ResolveStatic(config, resolver, svcpxyResolution);
        }

        private static Dictionary<String, String> ResolveStatic(String config, String resolver, ServiceProxyRequestResolution resolution)
        {
            // DEBUG
            System.Diagnostics.Trace.WriteLine("CONFIG = " + config);
            System.Diagnostics.Trace.WriteLine("RESOLVER = " + resolver);

            Dictionary<String, String> resolverInfo = new Dictionary<String, String>();
            Dictionary<String, String> resolverDictionary = new Dictionary<String, String>();
            Dictionary<String, String> facts = null;

            // Add keys from config
            // Add keys from resolver string
            // Add keys from resolution
            if (!resolver.Contains(@":\"))
            {
                resolver = resolver + @":\";
            }
            try
            {
                facts = ResolverMgr.GetFacts(config, resolver);
                resolution.ServiceName = ResolverMgr.GetConfigValue(facts, true, "serviceName");
                resolution.ServiceAction = ResolverMgr.GetConfigValue(facts, true, "serviceAction");
                resolution.ServiceType = ResolverMgr.GetConfigValue(facts, true, "serviceType");
                resolution.IsRequestResponse = Convert.ToBoolean(ResolverMgr.GetConfigValue(facts, true, "isRequestResponse"));
                resolution.TransformType = ResolverMgr.GetConfigValue(facts, false, "transformType");
                ServiceProxyResolutionManager.SetResolverDictionary(resolution, resolverDictionary);
                resolverInfo = resolverDictionary;
            }
            catch (Exception e)
            {
                EventLogger.Write(MethodBase.GetCurrentMethod(), e);
                throw;
            }
            finally
            {
                if (facts != null)
                {
                    facts.Clear();
                    facts = null;
                }
                if (resolution != null)
                {
                    resolution = null;
                }
                if (resolverDictionary != null)
                {
                    resolverDictionary = null;
                }
            }

            return resolverInfo;
        }

    }

    public class ServiceProxyResponseStaticResolver : IResolveProvider
    {
        Dictionary<string, string> IResolveProvider.Resolve(ResolverInfo resolverInfo, XLANGMessage message)
        {
            // Create instance of ServiceProxyResolution
            ServiceProxyResponseResolution svcpxyResolution = new ServiceProxyResponseResolution();

            // Call ResolveStatic
            return ResolveStatic(resolverInfo.Config, resolverInfo.Resolver, svcpxyResolution);
        }

        Dictionary<string, string> IResolveProvider.Resolve(string config, string resolver, System.Xml.XmlDocument message)
        {
            // Create instance of ServiceProxyResolution
            ServiceProxyResponseResolution svcpxyResolution = new ServiceProxyResponseResolution();

            // Call ResolveStatic
            return ResolveStatic(config, resolver, svcpxyResolution);
        }

        Dictionary<string, string> IResolveProvider.Resolve(string config, string resolver, IBaseMessage message, IPipelineContext pipelineContext)
        {
            // Create instance of ServiceProxyResolution
            ServiceProxyResponseResolution svcpxyResolution = new ServiceProxyResponseResolution();

            // Call ResolveStatic
            return ResolveStatic(config, resolver, svcpxyResolution);
        }

        private static Dictionary<String, String> ResolveStatic(String config, String resolver, ServiceProxyResponseResolution resolution)
        {
            // DEBUG
            System.Diagnostics.Trace.WriteLine("CONFIG = " + config);
            System.Diagnostics.Trace.WriteLine("RESOLVER = " + resolver);

            Dictionary<String, String> resolverInfo = new Dictionary<String, String>();
            Dictionary<String, String> resolverDictionary = new Dictionary<String, String>();
            Dictionary<String, String> facts = null;

            // Add keys from config
            // Add keys from resolver string
            // Add keys from resolution
            if (!resolver.Contains(@":\"))
            {
                resolver = resolver + @":\";
            }
            try
            {
                facts = ResolverMgr.GetFacts(config, resolver);
                resolution.MapInputType = ResolverMgr.GetConfigValue(facts, true, "responseMapInputType");
                resolution.TransformType = ResolverMgr.GetConfigValue(facts, false, "transformType");
                resolution.ValidateMethod = ResolverMgr.GetConfigValue(facts, true, "validationMethod");
                resolution.ValidateResponse = Convert.ToBoolean(ResolverMgr.GetConfigValue(facts, true, "validateResponse"));
                resolution.ValidationPolicyName = ResolverMgr.GetConfigValue(facts, false, "validationPolicyName");
                resolution.ValidationPolicyVersion = ResolverMgr.GetConfigValue(facts, false, "validationPolicyVersion");
                resolution.ValidationXsdType = ResolverMgr.GetConfigValue(facts, false, "validationSchemaStrongName");
                resolution.ValidationDocType = ResolverMgr.GetConfigValue(facts, false, "validationDocType");
                resolution.ValidationTrace = ResolverMgr.GetConfigValue(facts, false, "validationBreTrace");
                resolution.MergeContext = Convert.ToBoolean(ResolverMgr.GetConfigValue(facts, true, "mergeContext"));
                ServiceProxyResolutionManager.SetResolverDictionary(resolution, resolverDictionary);
                resolverInfo = resolverDictionary;
            }
            catch (Exception e)
            {
                EventLogger.Write(MethodBase.GetCurrentMethod(), e);
                throw;
            }
            finally
            {
                if (facts != null)
                {
                    facts.Clear();
                    facts = null;
                }
                if (resolution != null)
                {
                    resolution = null;
                }
                if (resolverDictionary != null)
                {
                    resolverDictionary = null;
                }
            }

            return resolverInfo;
        }
    }
}
